# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
#     https://docs.fastlane.tools/actions
#
# For a list of all available plugins, check out
#
#     https://docs.fastlane.tools/plugins/available-plugins
#

require 'json'

default_platform(:ios)

ENV["FASTLANE_SKIP_UPDATE_CHECK"] = "1"
ENV["SPACESHIP_SKIP_2FA_UPGRADE"] = "1"

project_path = ENV["PROJECT_PATH"] || "Examples.xcodeproj"
entitlement_path = "../Sources/Examples/Examples_CarPlay.entitlements"
entitlement_absolute_path = File.absolute_path(entitlement_path)

def read_json file_path, key
  JSON.parse(File.read(file_path))[key]
end

def examples_changelog
  maps = read_json(File.absolute_path('../Sources/MapboxMaps/MapboxMaps.json'), 'version')
  "Bump MapboxMaps version to #{maps}"
end

puts "Project Path: #{project_path}"
puts "Entitlement Path: #{entitlement_absolute_path}"

platform :ios do

  lane :setup_distribution_cert do
    setup_ci
    match(type: "appstore")
  end

  private_lane :api_key_if_needed do
    # We recommend to have api key on local machines to improve sign-in experience
    # While on the CI we will use api key components for the authentication
    # You can setup the api key by following the guide: https://github.com/mapbox/apple-internal/blob/master/guides/Modern%20authentification.md
    file_path = ENV['APP_STORE_CONNECT_API_KEY_PATH']

    if file_path.nil? || !File.exist?(file_path)
      app_store_connect_api_key
    end
  end

  desc "Setup code signing for a given project, target, and signing type"
  desc "Parameters:"
  desc "- project_path: Path to the Xcode project"
  desc "- target: Target name to configure"
  desc "- type: 'development' or 'appstore'"
  desc "Bundle identifier will be automatically extracted from the target"
  lane :setup_code_signing do |options|
    UI.message("Setting up code signing...")
    UI.message(options.inspect)
    proj_path = options[:project_path]
    target = options[:target]
    type = options[:type]

    UI.user_error!("project_path is required") unless proj_path
    UI.user_error!("target is required") unless target
    UI.user_error!("type is required (development or appstore)") unless type
    UI.user_error!("type must be 'development' or 'appstore'") unless ["development", "appstore"].include?(type)

    # Extract bundle identifier from the target's build settings
    begin
      build_settings_output = sh("xcodebuild -project '#{proj_path}' -target '#{target}' -showBuildSettings | grep 'PRODUCT_BUNDLE_IDENTIFIER'", log: false)
      app_identifier = build_settings_output.split('=').last.strip
      UI.user_error!("Could not extract PRODUCT_BUNDLE_IDENTIFIER from target #{target}") if app_identifier.empty?
      UI.message("Extracted app_identifier: #{app_identifier}")
    rescue => e
      UI.user_error!("Failed to extract bundle identifier from target #{target}: #{e.message}")
    end

    api_key_if_needed
    setup_circle_ci

    # Sync code signing with the extracted app identifier
    sync_code_signing(type: type, app_identifier: app_identifier, readonly: true)

    # Update code signing settings
    update_code_signing_settings(
      use_automatic_signing: false,
      path: proj_path,
      team_id: "GJZR2MEM28", # Developer Portal Team ID
      profile_name: lane_context[SharedValues::MATCH_PROVISIONING_PROFILE_MAPPING][app_identifier],
      targets: [target],
      code_sign_identity: "Apple Development: Created via API",
    )

    UI.success("Code signing setup complete for #{target} with #{type} signing")
  end

  lane :build_examples_tests do
    api_key_if_needed
    setup_circle_ci
    sync_code_signing
    update_code_signing_settings(
      use_automatic_signing: false,
      path: project_path,
      team_id: "GJZR2MEM28", # Developer Portal Team ID,
      profile_name: lane_context[SharedValues::MATCH_PROVISIONING_PROFILE_MAPPING]["mapbox.ExamplesUITests.xctrunner"],
      targets: ["ExamplesUITests"],
      code_sign_identity: "Apple Development: Created via API",
    )
    update_code_signing_settings(
      use_automatic_signing: false,
      path: project_path,
      team_id: "GJZR2MEM28", # Developer Portal Team ID,
      profile_name: lane_context[SharedValues::MATCH_PROVISIONING_PROFILE_MAPPING]["com.mapbox.examples"],
      targets: ["Examples"],
      code_sign_identity: "Apple Development: Created via API",
    )
    run_tests(
      project: project_path,
      scheme: 'Examples',                  # XCTest scheme
      clean: true,                        # Recommended: This would ensure the build would not include unnecessary files
      # Use the Debug mode here to avoid the compiler crash
      # https://github.com/apple/swift/issues/72117#issuecomment-1999619388
      # using the SWIFT_COMPILATION_MODE=incremental doesn't for this scheme.
      # configuration: "Release",
      configuration: "Debug",
      testplan: "Examples no unit tests",
      xcargs: "ENABLE_TESTABILITY=YES SWIFT_TREAT_WARNINGS_AS_ERRORS=NO COMPILER_INDEX_STORE_ENABLE=NO",
      skip_detect_devices: true,          # Required
      build_for_testing: true,            # Required
      sdk: 'iphoneos',                    # Required
      destination: "generic/platform=iOS", # Required
      should_zip_build_products: true,     # Must be true to set the correct format for Firebase Test Lab,
      result_bundle: true,
      output_directory: "output/",
      code_coverage: true
    )
  end

  lane :run_examples_firebase_tests do
    firebase_test_lab_ios_xctest(
      gcp_project: 'mapbox-maps-ios-dc24c', # Your Google Cloud project name
      devices: [                          # Device(s) to run tests on
        {
          ios_model_id: 'iphone11',        # Device model ID, see gcloud command above
          ios_version_id: '13.6',         # iOS version ID, see gcloud command above
        }
      ],
      timeout_sec: 20*60,
      skip_validation: true,
    )
  end

  desc "Test Examples scheme on Firebase Test Lab"
  lane :firebase_examples_tests do
    build_examples_tests
    run_examples_firebase_tests
  end

  lane :beta do
    api_key_if_needed # Generate API Token
    new_build_number = latest_testflight_build_number + 1
    increment_build_number(
      build_number: new_build_number,
      xcodeproj: project_path
    )

    if ENV['GITHUB_OUTPUT']
      File.open(ENV['GITHUB_OUTPUT'], 'a') do |file|
        file.puts("build_number=#{new_build_number}")
      end
    end

    build_and_submit
  end

  desc "Submit a new Beta Build to Apple TestFlight"
  desc "This will also make sure that the signing certificate and provisioning profiles are up to date."
  lane :build_and_submit do
    setup_circle_ci
    sync_code_signing(type: "development")
    update_code_signing_settings(
      use_automatic_signing: false,
      path: project_path,
      team_id: "GJZR2MEM28", # Developer Portal Team ID,
      profile_name: lane_context[SharedValues::MATCH_PROVISIONING_PROFILE_MAPPING]["com.mapbox.examples"],
      targets: ["Examples"],
      code_sign_identity: "Apple Development: Created via API",
      entitlements_file_path: entitlement_absolute_path
    )
    sync_code_signing(type: "appstore")
    build_app(
      scheme: "Examples",
      project: project_path,
      export_method: "app-store",
      destination: "generic/platform=iOS",
      xcargs: "SWIFT_TREAT_WARNINGS_AS_ERRORS=NO COMPILER_INDEX_STORE_ENABLE=NO" # Disable to bypass Deprecated error on OfflineManager example
    )
    upload_to_testflight(
      beta_app_feedback_email: "applemachine@mapbox.com",
      beta_app_description: "Examples app test build.",
      demo_account_required: false,
      skip_waiting_for_build_processing: false,
      distribute_external: true,
      groups: ["Mobot", "Mapbox Testers"],
      changelog: examples_changelog
    )
  end

  lane :build_tests do
    sh("cd .. && xcodegen")
    api_key_if_needed # Generate API Token
    setup_circle_ci
    sync_code_signing(app_identifier: "com.mapbox.MapboxMapsTestHost")
    update_code_signing_settings(
      use_automatic_signing: false,
      path: "MapboxMaps.xcodeproj",
      team_id: "GJZR2MEM28", # Developer Portal Team ID,
      profile_name: lane_context[SharedValues::MATCH_PROVISIONING_PROFILE_MAPPING]["com.mapbox.MapboxMapsTestHost"],
      targets: ["MapboxTestHost"],
      code_sign_identity: "Apple Development: Created via API",
    )
    run_tests(
      project: 'MapboxMaps.xcodeproj',
      scheme: 'MapboxTestHost',
      clean: true,
      configuration: "Release",
      # Use here SWIFT_COMPILATION_MODE=incremental to avoid the compiler crash
      # https://github.com/apple/swift/issues/72117#issuecomment-1999619388
      xcargs: "ENABLE_TESTABILITY=YES COMPILER_INDEX_STORE_ENABLE=NO SWIFT_COMPILATION_MODE=incremental",
      build_for_testing: true,
      destination: 'generic/platform=iOS',
      should_zip_build_products: true,
      output_directory: "output/",
      code_coverage: true
    )
  end

  lane :firebase_tests do
    build_tests
    firebase_test_lab_ios_xctest(
      gcp_project: 'mapbox-maps-ios-dc24c', # Your Google Cloud project name
      devices: [                          # Device(s) to run tests on
        {
          ios_model_id: 'iphone11',        # Device model ID, see gcloud command above
          ios_version_id: '13.6',         # iOS version ID, see gcloud command above
        }
      ],
      timeout_sec: 20*60,
      skip_validation: true,
    )
  end

end
